﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Aioms.Common;
using Aioms.Models;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.UnifyResult;
using Masuit.Tools;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using StackExchange.Profiling.Internal;

namespace Aioms.Controllers
{
    /// <summary>
    /// 任务计划
    /// </summary>
    [DynamicApiController]
    public class TaskPlanController
    {
        private readonly ISqlSugarClient db; // 核心对象：拥有完整的SqlSugar全部功能
        public TaskPlanController(ISqlSugarClient sqlSugarClient)
        {
            this.db = sqlSugarClient;
        }

        /// <summary>
        /// 计划列表
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="name"></param>
        /// <param name="type"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostList([FromForm] long eid, [FromForm] string name, [FromForm] string type, [FromForm] int pageIndex = 1, [FromForm] int pageSize = 10)
        {
            RefAsync<int> total = 0;
            List<TaskPlan> taskplans = await db.Queryable<TaskPlan>()
                .Where(tp => tp.IsDel == 0)
                .Where(tp => tp.Eid == eid)
                .WhereIF(!string.IsNullOrEmpty(name), tp => tp.Name.Contains(name))
                .WhereIF(!string.IsNullOrEmpty(type), tp => tp.Type == type)
                .OrderBy(tp => tp.Id, OrderByType.Desc)
                .ToPageListAsync(pageIndex, pageSize, total);
            UnifyContext.Fill(new { Total = total });
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = taskplans,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="taskplan"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostSave([FromForm] long eid, [FromForm] TaskPlan taskplan)
        {
            long id = await db.Insertable<TaskPlan>(taskplan).ExecuteReturnIdentityAsync();
            /*
            // 如果是年计划，直接生成当天工单
            if (taskplan.Period.Equals("年") && DateTime.Now.Date.Equals(taskplan.BeginDate.Date)) {
                // 发送到工单数据库
                await db.Insertable<WorkOrder>(new WorkOrder { Eid = taskplan.Eid, Number = DateTime.Now.ToString("yyyyMMddHHmmss"), Source = "计划", RefId = id, Name = taskplan.Name, Type = taskplan.Type.Replace("计划", "工单"), Extra = taskplan.Period, BeginTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " " + taskplan.BeginTime), EndTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " " + taskplan.EndTime), ManHour = taskplan.ManHour, Epids = taskplan.Epids, Imageurl = "", Videourl = "", Voiceurl = "", Status = "未开始" }).ExecuteCommandAsync();
            }*/
            if (taskplan.Period.Equals("临时") && DateTime.Now.Date.Equals(taskplan.BeginDate.Date))
            {
                JObject ti = new();
                if (taskplan.Type.Equals("巡检计划"))
                {
                    ti = JObject.FromObject(GetXunJianData(taskplan.RefIds.ToInt32()).Result);
                }
                else if (taskplan.Type.Equals("点检计划"))
                {
                    ti = JObject.FromObject(GetDianJianData(taskplan.RefIds).Result);
                }
                else if (taskplan.Type.Equals("保养计划"))
                {
                    ti = JObject.FromObject(GetBaoYangData(taskplan.RefIds).Result);
                }
                else
                {

                }
                // 发送到工单数据库
                await db.Insertable<TpWorkOrder>(new TpWorkOrder { Eid = eid, Number = DateTime.Now.ToString("yyyyMMddHHmmss"), Source = taskplan.Source, RefId = id, Name = taskplan.Name, Type = taskplan.Type.Replace("计划", "工单"), Extra = taskplan.Period, BeginTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " " + taskplan.BeginTime), EndTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " " + taskplan.EndTime), ManHour = taskplan.ManHour, SjBeginTime = DateTime.MinValue, SjEndTime = DateTime.MinValue, SjManHour = 0, Epids = taskplan.Epids, Imageurl = "", Videourl = "", Voiceurl = "", Status = "未开始", SjWxEpId = 0, SjWxEpRealname = "", Progress = "", TaskInfo = ti }).ExecuteCommandAsync();
            }
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = null,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        /// <summary>
        /// 日历展示
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="search_date"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostShowcalendar([FromForm] long eid, [FromForm] string search_date, [FromForm] string type)
        {
            string[] searchDataArr = search_date.Split("-");
            int day_of_month = DateTime.DaysInMonth(Convert.ToInt32(searchDataArr[0]), Convert.ToInt32(searchDataArr[1]));  // 本月多少天

            JArray data = new();
            // 查询每一天的周计划、月计划、年计划
            for (int i = 1; i <= day_of_month; i++)
            {
                JObject jo_taskPlan = new();

                String current_date = search_date + "-" + i;
                int day_of_week = ((int)DateTime.Parse(current_date).DayOfWeek); // 本周几

                // 当前日期
                String format_date = DateTime.Parse(current_date).ToString("yyyy-MM-dd");

                // 临时计划
                List<TaskPlan> temp_taskPlanList = await db.Queryable<TaskPlan>().Where(tp => tp.Eid == eid)
                    .WhereIF(!string.IsNullOrEmpty(type), tp => tp.Type == type)
                    .Where(tp => tp.Period == "临时")
                    .Where(tp => tp.Status == "ok")
                    .Where(tp => DateTime.Parse(current_date) >= SqlFunc.ToDateShort(tp.BeginDate))
                    .ToListAsync();
                List<TaskPlan> filter_temp_taskPlanList = new();
                if (temp_taskPlanList?.Count > 0)
                {
                    foreach (var ttp in temp_taskPlanList)
                    {
                        String js_temp_date = ttp.BeginDate.ToString("yyyy-MM-dd");
                        if (js_temp_date.Equals(format_date))
                        {
                            filter_temp_taskPlanList.Add(ttp);
                        }
                    }
                }
                jo_taskPlan.Add("temp", filter_temp_taskPlanList == null ? null : JArray.FromObject(filter_temp_taskPlanList));

                // 周计划
                List<TaskPlan> week_taskPlanList = await db.Queryable<TaskPlan>().Where(tp => tp.Eid == eid)
                    .WhereIF(!string.IsNullOrEmpty(type), tp => tp.Type == type)
                    .Where(tp => tp.Period == "周")
                    .Where($"FIND_IN_SET({day_of_week}, period_day)")
                    .Where(tp => tp.Status == "ok")
                    .Where(tp => DateTime.Parse(current_date) >= SqlFunc.ToDateShort(tp.BeginDate))
                    .ToListAsync();
                jo_taskPlan.Add("week", week_taskPlanList == null ? null : JArray.FromObject(week_taskPlanList));

                // 月计划
                List<TaskPlan> month_taskPlanList = await db.Queryable<TaskPlan>().Where(tp => tp.Eid == eid)
                    .WhereIF(!string.IsNullOrEmpty(type), tp => tp.Type == type)
                    .Where(tp => tp.Period == "月")
                    .Where($"FIND_IN_SET({i}, period_day)")
                    .Where(tp => tp.Status == "ok")
                    .Where(tp => DateTime.Parse(current_date) >= SqlFunc.ToDateShort(tp.BeginDate))
                    .ToListAsync();
                jo_taskPlan.Add("month", month_taskPlanList == null ? null : JArray.FromObject(month_taskPlanList));

                // 年计划
                List<TaskPlan> year_taskPlanList = await db.Queryable<TaskPlan>().Where(tp => tp.Eid == eid)
                    .WhereIF(!string.IsNullOrEmpty(type), tp => tp.Type == type)
                    .Where(tp => tp.Period == "年")
                    .Where(tp => tp.Status == "ok")
                    .Where(tp => DateTime.Parse(current_date) >= SqlFunc.ToDateShort(tp.BeginDate))
                    .ToListAsync();
                List<TaskPlan> filter_year_taskPlanList = new();
                if (year_taskPlanList?.Count > 0)
                {
                    foreach (var ytp in year_taskPlanList)
                    {
                        // 计算出来年计划多少天后的日期
                        DateTime js_year_date = ytp.BeginDate.AddDays(Convert.ToInt32(ytp.PeriodDay));
                        String format_js_date = js_year_date.ToString("yyyy-MM-dd");

                        // 跟当前时间作比较，看是否是当天
                        if (format_date.Equals(format_js_date) || format_date.Equals(ytp.BeginDate.ToString("yyyy-MM-dd")))
                        {
                            filter_year_taskPlanList.Add(ytp);
                        }
                    }
                }
                jo_taskPlan.Add("year", filter_year_taskPlanList == null ? null : JArray.FromObject(filter_year_taskPlanList));
                data.Add(jo_taskPlan);
            }
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = data,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        /// <summary>
        /// 停用/启用
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostStop([FromForm] long eid, [FromForm] long id, [FromForm] string status)
        {
            await db.Updateable<TaskPlan>().SetColumns(tp => tp.Status == status).Where(tp => tp.Eid == eid && tp.Id == id).ExecuteCommandAsync();
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = null,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        /// <summary>
        /// 计划详情
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostShow([FromForm] long eid, [FromForm] long id)
        {
            TaskPlan taskplan = await db.Queryable<TaskPlan>().Where(tp => tp.Eid == eid && tp.Id == id).SingleAsync();
            InspectionLine inspectionline = null;
            List<Device> devices = null;
            if (taskplan != null)
            {
                if (taskplan.Source.Equals("line"))
                {
                    inspectionline = await db.Queryable<InspectionLine>().Where(il => il.Id == long.Parse(taskplan.RefIds)).SingleAsync();
                }
                else
                {
                    List<long> refids = taskplan.RefIds.Split(",").Select(long.Parse).ToList();
                    devices = await db.Queryable<Device>().Where(dv => refids.Contains(dv.Id)).ToListAsync();
                }
            }

            UnifyContext.Fill(new { InspectionLine = inspectionline, Devices = devices });
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = taskplan,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        /// <summary>
        /// 计划删除
        /// </summary>
        /// <param name="eid"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IActionResult> PostDelete([FromForm] long eid, [FromForm] long id)
        {
            await db.Updateable<TaskPlan>().SetColumns(tp => tp.IsDel == 1).Where(tp => tp.Eid == eid && tp.Id == id).ExecuteCommandAsync();
            
            return new JsonResult(new RESTfulResult<object>
            {
                StatusCode = 200,
                Succeeded = true,
                Data = null,
                Errors = null,
                Extras = UnifyContext.Take(),
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            });
        }

        [NonAction]
        public async Task<XunJianPlan> GetXunJianData(long id)
        {
            XunJianPlan xjp = new();

            // 第一步：查找巡检路线
            InspectionLine il = await db.Queryable<InspectionLine>().InSingleAsync(id);
            if (il != null)
            {
                xjp.Id = il.Id;
                xjp.Eid = il.Eid;
                xjp.Name = il.Name;
                xjp.IsDel = il.IsDel;
                // 第二步：查找巡检点
                List<InspectionPoint> ips = await db.Queryable<InspectionPoint>().Where(ip => ip.Ilid == il.Id && ip.IsDel == 0).ToListAsync();
                foreach (var ip in ips)
                {
                    XunJianDian xjd = new();
                    xjd.Id = ip.Id;
                    xjd.Eid = ip.Eid;
                    xjd.Name = ip.Name;
                    xjd.Position = ip.Position;
                    xjd.Range = ip.Range;
                    xjd.IsDel = ip.IsDel;
                    // 第三步：查找巡检点巡检项
                    List<InspectionOption> ios = await db.Queryable<InspectionOption>().Where(io => io.Ipid == ip.Id).ToListAsync();
                    foreach (var io in ios)
                    {
                        XunJianDianXunJianXiang xjdxjx = new();
                        xjdxjx.Id = io.Id;
                        xjdxjx.Eid = io.Eid;
                        xjdxjx.Procedure = io.Procedure;
                        xjdxjx.Record = io.Record;
                        xjdxjx.Option = io.Option;
                        xjdxjx.ImageUrl = io.Image;
                        xjdxjx.VideoUrl = io.Video;

                        xjd.XunJianXiangs.Add(xjdxjx);
                    }
                    // 第四步：查找设备
                    if (!string.IsNullOrEmpty(ip.Dvids))
                    {
                        List<Device> devices = await db.Queryable<Device>().Where($"json_contains('{ip.Dvids}', json_array(id))").ToListAsync();
                        foreach (var device in devices)
                        {
                            XunJianDevice xjdv = new();
                            xjdv.Id = device.Id;
                            xjdv.Eid = device.Eid;
                            xjdv.Name = device.Name;
                            xjdv.AeName = device.Aename;
                            xjdv.Position = device.Position;
                            xjdv.IsDel = device.IsDel;
                            xjdv.Number = device.Number;
                            xjdv.Specification = device.Specification;
                            xjdv.AeId = device.Aeid;
                            xjdv.DvtId = device.Dvtid;
                            xjdv.DvtName = device.Dvtname;

                            // 第五步：根据设备类型查找巡检项
                            List<InspectionStandard> istds = await db.Queryable<InspectionStandard>().Where(istd => istd.Dvtid == device.Dvtid).ToListAsync();
                            foreach (var istd in istds)
                            {
                                DeviceXunJianStandard dxjs = new();
                                dxjs.Id = istd.Id;
                                dxjs.Eid = istd.Eid;
                                dxjs.Procedure = istd.Procedure;
                                dxjs.Record = istd.Record;
                                dxjs.Option = istd.Option;
                                dxjs.ImageUrl = istd.ImgUrl;
                                dxjs.VideoUrl = istd.VideoUrl;

                                xjdv.DeviceXunJianStandards.Add(dxjs);
                            }

                            xjd.XunJianDevices.Add(xjdv);
                        }
                    }

                    xjp.XunJianDians.Add(xjd);
                }
            }
            return xjp;
        }

        [NonAction]
        public async Task<DianJianPlan> GetDianJianData(string dvids)
        {
            DianJianPlan djp = new();

            // 第一步：查找设备
            List<Device> devices = await db.Queryable<Device>().Where($"FIND_IN_SET(id, '{dvids}')").ToListAsync();
            foreach (var device in devices)
            {
                DianJianDevice djdv = new();
                djdv.Id = device.Id;
                djdv.Eid = device.Eid;
                djdv.Name = device.Name;
                djdv.AeName = device.Aename;
                djdv.Position = device.Position;
                djdv.IsDel = device.IsDel;
                djdv.Number = device.Number;
                djdv.Specification = device.Specification;
                djdv.AeId = device.Aeid;
                djdv.DvtId = device.Dvtid;
                djdv.DvtName = device.Dvtname;

                // 第二步：根据设备类型查找巡检项
                List<PointInspectionStandard> pistds = await db.Queryable<PointInspectionStandard>().Where(pistd => pistd.Dvtid == device.Dvtid).ToListAsync();
                foreach (var pistd in pistds)
                {
                    DeviceDianJianStandard ddjs = new();
                    ddjs.Id = pistd.Id;
                    ddjs.Eid = pistd.Eid;
                    ddjs.Standard = pistd.Standard;
                    ddjs.Record = pistd.Record;
                    ddjs.Option = pistd.Option;
                    ddjs.Position = pistd.Position;
                    ddjs.ImageUrl = pistd.ImgUrl;
                    ddjs.VideoUrl = pistd.VideoUrl;

                    djdv.DeviceDianJianStandards.Add(ddjs);
                }

                djp.DianJianDevices.Add(djdv);
            }
            return djp;
        }

        [NonAction]
        public async Task<BaoYangPlan> GetBaoYangData(string dvids)
        {
            BaoYangPlan byp = new();

            // 第一步：查找设备
            List<Device> devices = await db.Queryable<Device>().Where($"FIND_IN_SET(id, '{dvids}')").ToListAsync();
            foreach (var device in devices)
            {
                BaoYangDevice bydv = new();
                bydv.Id = device.Id;
                bydv.Eid = device.Eid;
                bydv.Name = device.Name;
                bydv.AeName = device.Aename;
                bydv.Position = device.Position;
                bydv.IsDel = device.IsDel;
                bydv.Number = device.Number;
                bydv.Specification = device.Specification;
                bydv.AeId = device.Aeid;
                bydv.DvtId = device.Dvtid;
                bydv.DvtName = device.Dvtname;

                // 第二步：根据设备类型查找巡检项
                List<MaintenanceStandard> pistds = await db.Queryable<MaintenanceStandard>().Where(pistd => pistd.Dvtid == device.Dvtid).ToListAsync();
                foreach (var pistd in pistds)
                {
                    DeviceBaoYangStandard dbys = new();
                    dbys.Id = pistd.Id;
                    dbys.Eid = pistd.Eid;
                    dbys.Standard = pistd.Standard;
                    dbys.Position = pistd.Position;
                    dbys.ImageUrl = pistd.ImgUrl;
                    dbys.VideoUrl = pistd.VideoUrl;

                    bydv.DeviceBaoYangStandards.Add(dbys);
                }

                byp.BaoYangDevices.Add(bydv);
            }
            return byp;
        }
    }
}
